package com.aizhixin.lab.project.course.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.aizhixin.lab.account.dto.AccountDTO;
import com.aizhixin.lab.common.core.ApiReturnConstants;
import com.aizhixin.lab.common.core.DataValidity;
import com.aizhixin.lab.common.dto.SortDTO;
import com.aizhixin.lab.common.utils.PageJdbcUtil;
import com.aizhixin.lab.company.entity.User;
import com.aizhixin.lab.company.repository.UserRepository;
import com.aizhixin.lab.docker.domain.Image;
import com.aizhixin.lab.project.course.core.TaskStatus;
import com.aizhixin.lab.project.course.domain.AddTeacherDomain;
import com.aizhixin.lab.project.course.entity.*;
import com.aizhixin.lab.project.course.repository.*;
import com.aizhixin.lab.project.course.vo.*;
import com.aizhixin.lab.project.template.domain.*;
import com.aizhixin.lab.project.template.entity.*;
import com.aizhixin.lab.project.template.repository.*;
import com.aizhixin.lab.project.template.service.ModuleTaskService;
import com.aizhixin.lab.project.template.service.ProjectModuleService;
import com.aizhixin.lab.project.template.service.ProjectService;
import com.aizhixin.lab.project.template.service.WorkOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class StudentProjectService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private PageJdbcUtil pageJdbcUtil;

    @Autowired
    private ProjectGroupTaskRepository projectGroupTaskRepository;

    @Autowired
    private ProjectPostRepository projectPostRepository;

    @Autowired
    private ProjectSkillRepository projectSkillRepository;

    @Autowired
    private KnowledgePointRepository knowledgePointRepository;

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private TeacherProjectRepository teacherProjectRepository;

    @Autowired
    private ProjectCourseRepository projectCourseRepository;

    @Autowired
    private ProjectClassStuRepository projectClassStuRepository;

    @Autowired
    private ProjectRoleRepository projectRoleRepository;

    @Autowired
    private ProjectStuKnowledgeScoreRepository projectStuKnowledgeScoreRepository;

    @Autowired
    private ProjectStuSkillScoreRepository projectStuSkillScoreRepository;

    public ProjectTaskProgressVo findTaskProgress(String projectId, String groupId){
        ProjectTaskProgressVo taskProgressVo = new ProjectTaskProgressVo();
        List<ProjectGroupTask> groupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndDeleteFlag(projectId,groupId,0);
        Map<String,List<ProjectGroupTask>> statusMap = groupTaskList.stream().collect(Collectors.groupingBy(b -> b.getTaskStatus()));
        for(Map.Entry<String, List<ProjectGroupTask>> entry : statusMap.entrySet()){
            String mapKey = entry.getKey();
            List<ProjectGroupTask> mapValue = entry.getValue();
            if (mapKey.equals("init")){
                taskProgressVo.setNoBegin(mapValue.size());
            }else if (mapKey.equals("running")){
                taskProgressVo.setBegining(mapValue.size());
            }else if (mapKey.equals("approved")){
                taskProgressVo.setCompleted(mapValue.size());
                taskProgressVo.setCompletedRate(groupTaskList.size()/mapValue.size());
            }else if (mapKey.equals("timeout")){
                taskProgressVo.setDelay(mapValue.size());
                taskProgressVo.setDelayRate(groupTaskList.size()/mapValue.size());
            }
        }
        taskProgressVo.setAll(groupTaskList.size());
        return taskProgressVo;
    }

    public List<ProjectMemberContributeVo> findMemberContribute(String projectId, String groupId){
        List<ProjectMemberContributeVo> contributeVoList = new ArrayList<>();
        List<ProjectGroupTask> groupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndDeleteFlag(projectId,groupId,0);
        Map<Long,List<ProjectGroupTask>> statusMap = groupTaskList.stream().collect(Collectors.groupingBy(b -> b.getStuId()));
        Integer taskCount = groupTaskList.size();
        for(Map.Entry<Long, List<ProjectGroupTask>> entry : statusMap.entrySet()) {
            ProjectMemberContributeVo memberContributeVo = new ProjectMemberContributeVo();
            Long mapKey = entry.getKey();
            List<ProjectGroupTask> mapValue = entry.getValue();
            User user = userRepository.findOne(mapKey);
            memberContributeVo.setName(user.getName());
            memberContributeVo.setValue(taskCount/mapValue.size());
            contributeVoList.add(memberContributeVo);
        }
        return contributeVoList;
    }

    public List findMemberContributeChart(String projectId, String groupId){
        List<ProjectGroupTask> groupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndDeleteFlag(projectId,groupId,0);
        Map<Long,List<ProjectGroupTask>> statusMap = groupTaskList.stream().collect(Collectors.groupingBy(b -> b.getStuId()));
        Integer taskCount = groupTaskList.size();
        List list = new ArrayList();
        for(Map.Entry<Long, List<ProjectGroupTask>> entry : statusMap.entrySet()) {
            Map map = new HashMap();
            Long mapKey = entry.getKey();
            List<ProjectGroupTask> mapValue = entry.getValue();
            User user = userRepository.findOne(mapKey);
            map.put("name",user.getName());
            map.put("count",taskCount/mapValue.size());
            list.add(map);
        }
        return list;
    }

    public Map findReleaseTask(String projectId, String groupId){
        Map map = new HashMap();
        List<Date> dateList = new ArrayList<>();
        List<Integer> startCountList = new ArrayList<>();
        List<Integer> endCountList = new ArrayList<>();
        List<ProjectGroupTask> groupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndDeleteFlagOrderByCreatedDateDesc(projectId,groupId,0);
        Map<String,List<ProjectGroupTask>> statusMap = groupTaskList.stream().collect(Collectors.groupingBy(b -> b.getTaskStatus()));
        Map<Date,List<ProjectGroupTask>> createDateMap = groupTaskList.stream().collect(Collectors.groupingBy(b -> b.getCreatedDate()));
        for(Map.Entry<Date, List<ProjectGroupTask>> entry : createDateMap.entrySet()) {
            dateList.add(entry.getKey());
            List<ProjectGroupTask> mapValue = entry.getValue();
            startCountList.add(mapValue.size());
        }
        List<String> list=new ArrayList<>();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        dateList.forEach(date->{
            list.add(formatter.format(date));
        });
        list.sort(Comparator.naturalOrder());
        for(Map.Entry<String, List<ProjectGroupTask>> entry : statusMap.entrySet()){
            String mapKey = entry.getKey();
            if (mapKey.equals("approved")){
                for (ProjectGroupTask data:entry.getValue()) {
                    if (data.getRealityEndDate()==null){
                        continue;
                    }
                    if (list.contains(formatter.format(data.getRealityEndDate()))){
                        continue;
                    }
                    dateList.add(data.getRealityEndDate());
                    endCountList.add(entry.getValue().size());
                }
            }
        }
        List<Date> timeData = dateList.stream().distinct().collect(Collectors.toList());
//        Set<String> list=new HashSet<>();
//        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        list.clear();
        timeData.forEach(date->{
            list.add(formatter.format(date));
        });
        map.put("timeList", list);
        map.put("startCountList",startCountList);
        map.put("endCountList",endCountList);
        return map;
    }

    public List<ProjectTaskConditionVo> findTaskCondition(String projectId, String groupId,Long sutId){
        Map<String,Object> map = new HashMap();
        List<ProjectTaskConditionVo> taskConditionVoList = new ArrayList<>();
        List<ProjectGroupTask> groupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndStuIdAndDeleteFlag(projectId,groupId,sutId,0);
        Integer groupCount = groupTaskList.size();
        Map<String,List<ProjectGroupTask>> statusMap = groupTaskList.stream().collect(Collectors.groupingBy(b -> b.getTaskStatus()));
        Integer total=0;
        Integer init=0;
        Integer approved=0;
        Integer timeout=0;
        Integer pending=0;

        for(Map.Entry<String, List<ProjectGroupTask>> entry : statusMap.entrySet()){
            String mapKey = entry.getKey();
            total++;
            if (mapKey.equals("init")){
                init++;
                map.put("未开始",init);
            }else if (mapKey.equals("pending")){
                pending++;
                map.put("进行中",pending);

            }else if (mapKey.equals("approved")){
                approved++;
                map.put("已完成",approved);

            }else if (mapKey.equals("timeout")){
                timeout++;
                map.put("已延期",timeout);
            }
        }
        for(String entry : map.keySet()){
            ProjectTaskConditionVo taskConditionVo = new ProjectTaskConditionVo();
            taskConditionVo.setTaskStatus(entry);
            taskConditionVo.setNumber((Integer) map.get(entry));
            taskConditionVo.setRatio(total==0?0:taskConditionVo.getNumber()*100/total);
            taskConditionVoList.add(taskConditionVo);
        }
        return taskConditionVoList;
    }

    public List<NameValueVo> findTaskScore(String projectId, String groupId,Long sutId){
        String sql = "SELECT a.task_grade as score,b.task_name as name FROM c_project_group_task a left join c_module_task b on a.task_id=b.id where a.project_id = '"+projectId+"' and a.group_id = '"+groupId+"' and a.stu_id = " + sutId;
        return pageJdbcUtil.getInfo(sql,nameValueVoRowMapper);
    }

    RowMapper<NameValueVo> nameValueVoRowMapper = new RowMapper<NameValueVo>() {
        @Override
        public NameValueVo mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            NameValueVo infoVo = new NameValueVo();
            infoVo.setValue(rs.getInt("score"));
            infoVo.setName(rs.getString("name"));
            return infoVo;
        }
    };

    public List<TaskAccomplishConditionVo> findGroupTask(String projectId, String groupId,Long sutId) {
        String sql = "select a.role,b.name,a.stu_id from c_project_class_stu a left join t_user b on a.stu_id = b.id where a.project_id = '" + projectId + "' and a.group_id = '" + groupId + "'";
        List<TaskAccomplishConditionVo> list = pageJdbcUtil.getInfo(sql, taskAccomplishConditionVoRowMapper);
        list.forEach(item -> {
            int init = projectGroupTaskRepository.countByProjectIdAndGroupIdAndTaskStatusAndDeleteFlagAndStuId(projectId, groupId, "init", 0, item.getStuId());
            int running = projectGroupTaskRepository.countByProjectIdAndGroupIdAndTaskStatusAndDeleteFlagAndStuId(projectId, groupId, "pending", 0, item.getStuId());
            int approved = projectGroupTaskRepository.countByProjectIdAndGroupIdAndTaskStatusAndDeleteFlagAndStuId(projectId, groupId, "approved", 0, item.getStuId());
            int timeout = projectGroupTaskRepository.countByProjectIdAndGroupIdAndTaskStatusAndDeleteFlagAndStuId(projectId, groupId, "timeout", 0, item.getStuId());
            item.setInit(init);
            item.setApproved(approved);
            item.setRunning(running);
            item.setTimeout(timeout);
        });
        int init = list.stream().filter(BizData -> BizData.getInit() != null).mapToInt(TaskAccomplishConditionVo::getInit).sum();
        int approved = list.stream().filter(BizData -> BizData.getApproved() != null).mapToInt(TaskAccomplishConditionVo::getApproved).sum();
        int running = list.stream().filter(BizData -> BizData.getRunning() != null).mapToInt(TaskAccomplishConditionVo::getRunning).sum();
        int timeout = list.stream().filter(BizData -> BizData.getTimeout() != null).mapToInt(TaskAccomplishConditionVo::getTimeout).sum();
        TaskAccomplishConditionVo taskAccomplishConditionVo = new TaskAccomplishConditionVo();
        taskAccomplishConditionVo.setApproved(approved);
        taskAccomplishConditionVo.setTimeout(timeout);
        taskAccomplishConditionVo.setInit(init);
        taskAccomplishConditionVo.setRunning(running);
        taskAccomplishConditionVo.setName("总计");
        list.add(taskAccomplishConditionVo);
        return list;
    }

    RowMapper<TaskAccomplishConditionVo> taskAccomplishConditionVoRowMapper = new RowMapper<TaskAccomplishConditionVo>() {
        @Override
        public TaskAccomplishConditionVo mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            TaskAccomplishConditionVo infoVo = new TaskAccomplishConditionVo();
            infoVo.setName(rs.getString("name"));
            infoVo.setRole(rs.getString("role"));
            infoVo.setStuId(rs.getLong("stu_id"));
            return infoVo;
        }
    };

    public List<TaskGroupSkillsknowledgeScoreVo> findGroupTaskGraspKnowledge(String projectId, String groupId) {
        String sql = "SELECT a.stu_id,b.NAME,c.`name` AS roloName FROM c_project_class_stu a LEFT JOIN t_user b ON a.stu_id = b.id LEFT JOIN t_project_role c ON a.role_id = c.id  WHERE a.project_id = '" + projectId + "' AND a.group_id = '" + groupId + "'";
        List<TaskGroupSkillsknowledgeScoreVo> list = pageJdbcUtil.getInfo(sql, TaskGroupSkillsknowledgeScoreVoRowMapper);
        List<ProjectGroupTask> projectGroupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndDeleteFlag(projectId,groupId,0);
        Map<Long,List<ProjectGroupTask>> longListMap = projectGroupTaskList.stream().collect(Collectors.groupingBy(ProjectGroupTask::getStuId));
        List<Long> stuIds = list.stream().map(TaskGroupSkillsknowledgeScoreVo::getStuId).collect(Collectors.toList());
        List<ProjectStuKnowledgeScore> projectStuKnowledgeScoreList = projectStuKnowledgeScoreRepository.findByProjectIdAndStuIdIn(projectId, stuIds);
        Map<Long,List<ProjectStuKnowledgeScore>> knowledgeMap = projectStuKnowledgeScoreList.stream().collect(Collectors.groupingBy(ProjectStuKnowledgeScore::getStuId));
        List<ProjectStuSkillScore> projectStuSkillScoreList = projectStuSkillScoreRepository.findByProjectIdAndStuIdIn(projectId, stuIds);
        Map<Long,List<ProjectStuSkillScore>> skillMap = projectStuSkillScoreList.stream().collect(Collectors.groupingBy(ProjectStuSkillScore::getStuId));
        list.forEach(item -> {
            projectStuSkillScoreList.forEach(skillScore -> {
                if (item.getStuId() == skillScore.getStuId()) {
                    List<ProjectStuKnowledgeScore> projectStuKnowledgeScores = knowledgeMap.get(skillScore.getStuId());
                    Long score = projectStuKnowledgeScores.stream().mapToLong(ProjectStuKnowledgeScore::getScore).sum();
                    item.setSkillPoints(score);
                }
            });
            projectStuKnowledgeScoreList.forEach(knowledgeScore -> {
                if (item.getStuId() == knowledgeScore.getStuId()) {
                    List<ProjectStuSkillScore> projectStuKnowledgeScores = skillMap.get(knowledgeScore.getStuId());
                    Long score = projectStuKnowledgeScores.stream().mapToLong(ProjectStuSkillScore::getScore).sum();
                    item.setKnowledgePoint(score);
                }
            });

            item.setScore(item.getKnowledgePoint()+ item.getSkillPoints());
            item.setTaskNum(longListMap.get(item.getStuId()).size());
            item.setContributeRatio(projectGroupTaskList.size()/longListMap.get(item.getStuId()).size());
        });
        return list;
    }

    RowMapper<TaskGroupSkillsknowledgeScoreVo> TaskGroupSkillsknowledgeScoreVoRowMapper = new RowMapper<TaskGroupSkillsknowledgeScoreVo>() {
        @Override
        public TaskGroupSkillsknowledgeScoreVo mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            TaskGroupSkillsknowledgeScoreVo infoVo = new TaskGroupSkillsknowledgeScoreVo();
            infoVo.setName(rs.getString("name"));
            infoVo.setRole(rs.getString("roloName"));
            infoVo.setStuId(rs.getLong("stu_id"));
            return infoVo;
        }
    };


    public Map findGraspKnowledge(String projectId, String groupId,Long sutId){
        Map map = new HashMap();
        List<String> postNameList = new ArrayList<>();
        List<String> knowledgeNameList = new ArrayList<>();
        List<ProjectPost> projectPostList = projectPostRepository.findByProjectIdAndDeleteFlag(projectId,0);
        List<String> postIds = projectPostList.stream().map(ProjectPost::getId).collect(Collectors.toList());
        List<ProjectSkill> projectSkillList = projectSkillRepository.findByPostIdInAndDeleteFlag(postIds,0);
        projectSkillList.forEach(item->{
            postNameList.add(item.getSkillName());
        });

        List<ProjectGroupTask> groupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndStuIdAndDeleteFlag(projectId,groupId,sutId,0);
        List<String> taskIds = groupTaskList.stream().map(ProjectGroupTask::getTaskId).collect(Collectors.toList());
        List<KnowledgePoint> knowledgePointList = knowledgePointRepository.findByModuleTaskIdIn(taskIds);
        knowledgePointList.forEach(item->{
            knowledgeNameList.add(item.getKnowledgePoint());
        });
        map.put("postNameList",postNameList);
        map.put("knowledgeNameList",knowledgeNameList);
        return map;
    }

    public Map findProjectCurriculum(String projectId){
        Map map = new HashMap();
        List list = new ArrayList();
        Map postChildren = new HashMap();
        Map skillChildren = new HashMap();
        List<Map> postList = new ArrayList<>();
        List<Map> skillList = new ArrayList<>();
        Project project = projectRepository.findOne(projectId);
        List<ProjectPost> projectPostList = projectPostRepository.findByProjectIdAndDeleteFlag(projectId,0);
        List<String> postNames = projectPostList.stream().map(ProjectPost::getPostName).collect(Collectors.toList());
        List<ProjectCourse> projectSkillList = projectCourseRepository.findByProjectId(projectId);
        postNames.forEach(item->{
            Map postMap = new HashMap();
            postMap.put("label",item);
            postList.add(postMap);
        });
        projectSkillList.forEach(item->{
            Map skillMap = new HashMap();
            skillMap.put("label",item.getCourseName());
            skillList.add(skillMap);
        });

        postChildren.put("label","相关职位");
        postChildren.put("children",postList);
        skillChildren.put("label","相关课程");
        skillChildren.put("children",skillList);
        list.add(postChildren);
        list.add(skillChildren);
        map.put("label",project.getProjectName());
        map.put("children",list);

        return map;
    }

    public Map findProjectInfo(String projectId,Long stuId) {
        Map map = new HashMap();
        TeacherProject project = teacherProjectRepository.findOne(projectId);
        ProjectClassStu projectClassStu = projectClassStuRepository.findByProjectIdAndStuIdAndDeleteFlag(projectId, stuId, 0);
        User teaUser = userRepository.getOne(project.getCreatedBy());
        if (projectClassStu.getRoleId() == null){
            map.put("language", project.getLanguage());
            map.put("projectCreate", teaUser.getName());
            map.put("stasut", "正常");
            map.put("startTime", DateUtil.formatDate(project.getCreatedDate()));
            map.put("roleName", "");
            return map;
        }
        ProjectRole projectRole =  projectRoleRepository.findOne(projectClassStu.getRoleId());
//        List<ProjectGroupTask> projectGroupTaskList = projectGroupTaskRepository.findByProjectIdAndGroupIdAndStuIdAndDeleteFlag(projectId,groupId,stuId,0);
//        projectGroupTaskList.forEach(item->{
//            if (new Date().compareTo(item.getRealityEndDate()) == -1){
//                map.put("schedule", "正常");
//            }else if (new Date().compareTo(item.getRealityEndDate()) == 1){
//                map.put("schedule", "延期");
//            }
//        });
        map.put("language", project.getLanguage());
        map.put("projectCreate", teaUser.getName());
        map.put("stasut", "正常");
        map.put("startTime", DateUtil.formatDate(project.getCreatedDate()));
        map.put("roleName", projectRole.getRoleName());
        return map;
    }
    RowMapper<StuTaskVo> stuTaskVoRowMapper = new RowMapper<StuTaskVo>() {

        @Override
        public StuTaskVo mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            StuTaskVo stuTaskVo = new StuTaskVo();
            stuTaskVo.setId(rs.getString("id"));
            stuTaskVo.setTaskId(rs.getString("task_id"));
            stuTaskVo.setTaskName(rs.getString("task_name"));
            stuTaskVo.setTaskDesc(rs.getString("task_desc"));
            stuTaskVo.setTaskNo(rs.getInt("task_no"));
            stuTaskVo.setUserName(rs.getString("name"));
            stuTaskVo.setBeginDate(rs.getDate("reality_begin_date"));
            stuTaskVo.setSuggestTime(rs.getInt("suggest_time"));
            stuTaskVo.setTaskStatus(rs.getString("task_status"));
            stuTaskVo.setGroupMemberId(rs.getLong("stu_id"));
            stuTaskVo.setWorkOrderName(rs.getString("order_name"));
            return stuTaskVo;
        }
    };

    /**
     * 获取任务下小组信息
     * @param groupId
     * @param moduleId
     * @return
     */
    public Map<String, Object> stuTaskVoList(String groupId, String moduleId, Long stuId, String taskStatus, Integer pageSize, Integer pageNumber){
        String sql="SELECT cmt.id task_id,cpgt.id, cmt.task_name,cpgt.stu_id,cmt.task_desc,cmt.task_no,tu.`name`,cpgt.reality_begin_date,cmt.suggest_time,cpgt.task_status,ctwo.w_name order_name FROM c_project_group_task cpgt LEFT JOIN c_module_task cmt ON cpgt.task_id=cmt.id LEFT JOIN t_user tu ON tu.id=cpgt.stu_id LEFT JOIN c_task_work_order ctwo ON ctwo.id=cpgt.work_order_id WHERE cmt.module_id='"+moduleId+"' AND cpgt.delete_flag=0 ";
        String countSql="SELECT count(*) FROM c_project_group_task cpgt LEFT JOIN c_module_task cmt ON cpgt.task_id=cmt.id LEFT JOIN t_user tu ON tu.id=cpgt.stu_id WHERE cmt.module_id='"+moduleId+"' AND cpgt.delete_flag=0 ";
        if(!StringUtils.isEmpty(taskStatus)){
            sql+=" AND cpgt.task_status='"+taskStatus+"'";
            countSql+=" AND cpgt.task_status='"+taskStatus+"'";
        }
        if (!StringUtils.isEmpty(groupId)){
            sql+=" AND cpgt.group_id='"+groupId+"'";
            countSql+=" AND cpgt.group_id='"+groupId+"'";
        }else{
            sql+=" AND cpgt.stu_id="+stuId+" ";
            countSql+=" AND cpgt.stu_id="+stuId+" ";
        }

        List<SortDTO> sort = new ArrayList<SortDTO>();
        SortDTO dto = new SortDTO();
        dto = new SortDTO();
        dto.setKey("cmt.task_no");
        dto.setAsc(true);
        sort.add(dto);
        return pageJdbcUtil.getPageInfor(pageSize,pageNumber,stuTaskVoRowMapper,sort,sql,countSql);
    }


}
